﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Common
{
    public abstract class MessageLooperBase
    {
        public class WorkItem
        {
            public int type;
            public object data;
        }
        Thread _holderThread;
        private Queue<WorkItem> _taskQueue;

        AutoResetEvent _queueEvent;
        AutoResetEvent _interruptedEvent;
        WaitHandle[] _syncEvents;
        bool _enterLoop = false;
       
        public MessageLooperBase()
        {
            _taskQueue = new Queue<WorkItem>();
            _queueEvent = new AutoResetEvent(false);
            _interruptedEvent = new AutoResetEvent(false);
            _holderThread = new Thread(new ThreadStart(doWork));

            _syncEvents = new WaitHandle[2];
            _syncEvents[0] = _queueEvent;
            _syncEvents[1] = _interruptedEvent;
            _enterLoop = false;
            //mLogger = new NewLogger(GetType().Name);
        }

        public virtual void start()
        {
            _enterLoop = false;
            _holderThread.Start();
            while (!_enterLoop)
            {
                Thread.Sleep(10);
            }
        }

        protected void doWork()
        {
            //mLogger.debug(GetType().Name + "start!");
            lock (_taskQueue)
            {
                _taskQueue.Clear();
            }
            _enterLoop = true;
            while (true)
            {
                try
                {
                    WorkItem task = getTaskFromQueue();
                    if (task != null)
                    {
                        handleItem(task);
                    }
                    else
                    {

                        WaitHandle.WaitAny(_syncEvents, -1);
                    }
                }
                catch (Exception ex)
                {
                   // mLogger.debug(ex);
                    break;
                }

            }
        }

        protected abstract void handleItem(WorkItem anItem);


        protected WorkItem getTaskFromQueue()
        {
            lock (_taskQueue)
            {
                if (_taskQueue.Count != 0)
                {
                    return _taskQueue.Dequeue();
                }
                else
                {
                    return null;
                }
            }
        }
        public void stop()
        {
            _holderThread.Interrupt();
            if (_holderThread.IsAlive)
                _holderThread.Abort();
            _holderThread = new Thread(new ThreadStart(doWork));
            _enterLoop = false;
        }
        public void QueueItem(WorkItem item)
        {
            lock (_taskQueue)
            {
                _taskQueue.Enqueue(item);
            }
            _queueEvent.Set();
        }
        public abstract void OnExited();


    }
}
